#pragma once

// 在这里包含全部头文件而不是前置声明，用户只需要引入一个TcpServer.h就能用
// #include <functional>
// #include <string>
// #include <memory>
// #include <atomic>
// #include <unordered_map>

#include "./reactor/EventLoop.h"
#include "./net/InetAddress.h"
#include "./reactor/Acceptor.h"
#include "./reactor/EventLoopThreadPool.h"
#include "./reactor/Callbacks.h"
#include "./reactor/TcpConnection.h"
// #include "./common/Noncopyable.h"
// #include "./Buffer.h"

// 开发者服务器编程使用
class TcpServer
{
public:
    using ThreadInitCallback = std::function<void(EventLoop *)>;

    // OPTIMIZE: enum -> enum class
    enum class ListenOption
    {
        NoReusePort,
        ReusePort
    };

    TcpServer(EventLoop *loop,
              const InetAddress &listenAddr,
              ListenOption listenOpt, // 实际是整型，不用const &
              const std::string &threadName);
    ~TcpServer();

    void setThreadNum(int numThreads);
    void setThreadInitCallback(const ThreadInitCallback &cb);

    void setConnectionCallback(const ConnectionCallback &cb);
    void setReadWriteCallback(const ReadWriteCallback &cb);
    void setWriteCompleteCallback(const WriteCompleteCallback &cb);

    void start(); // 原子状态标志isStart_防止多次调用->多次调用无副作用，线程安全

private:
    void newConnection(int sockfd, const InetAddress &peerAddr);
    void removeConnection(const TcpConnectionPtr &conn);
    void removeConnectionInLoop(const TcpConnectionPtr &conn);

    EventLoop *loop_; // 所属loop，用户自定义并传入的mainloop
    const std::string ipPort_;
    std::unique_ptr<Acceptor> acceptor_; // 运行在mainloop，监听连接事件

    const std::string threadName_; // 线程池相关命名
    // OPTIMIZE:  std::shared_ptr<> ->  std::unique_ptr<>
    std::unique_ptr<EventLoopThreadPool> threadPool_;

    // TODO: 单纯标识id用于日志输出，可以不需要
    // OPTIMIZE: 类内默认初始化而不是在构造时初始化
    int connId_ = 1;

    // OPTIMIZE: atomic_int -> atomic_bool
    std::atomic_bool isStart_ = false; // 防止一个TcpServer对象被start多次的状态标志

    // 用户/开发者设置的回调
    int threadNum_;                         // 线程池线程数量，不包括主线程
    ThreadInitCallback threadInitCallback_; // 线程初始化回调

    ConnectionCallback connectionCallback_;       // 有新连接回调
    ReadWriteCallback readWriteCallback_;         // 有读写回调
    WriteCompleteCallback writeCompleteCallback_; // 写完成回调

    using ConnectionMap = std::unordered_map<std::string, TcpConnectionPtr>; // 名称-连接
    ConnectionMap conns_;                                                    // 所有连接
};